/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>

/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>

#include <securec.h>
#include <vector>

#include "channel_operations_mock.h"
#include "pin_auth_core.h"
#include "test_helpers.h"

namespace OHOS {
namespace SeBaseServices {
namespace UnitTest {
using namespace testing;

TEST(PinAuthCoreTest, ProcPinAuthCmdEnrollLocalTestCaseSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80010000"                         // apdu header
                      "44"                               // 0x44 input
                      "00001234"                         // slotId = 0x1234
                      "0102030405060708090A0B0C0D0E0F10" // hash data
                      "00000000000000000000000000000000" //
                      "00000000000000000000000000000000" //
                      "00000000000000000000000000000000" //
                      "00";                              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "11223344556677889900AABBCCDDEEFF" // 32-bit secret
                      "11111111111111111111111111111111"
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinDataHash hash = {.data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}};
    PinDataSecret secret = {.data = {0}};
    auto ret = ProcPinAuthCmdEnrollLocal(&channel, 0x1234, &hash, &secret);
    EXPECT_EQ(ret, SUCCESS);

    std::string expect = "11223344556677889900AABBCCDDEEFF"
                         "11111111111111111111111111111111";
    EXPECT_EQ(TestHelpers::VectorToHexString(secret.data, PIN_DATA_SECRET_LEN), expect);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdEnrollLocalCaseOutApduSizeIsSmall)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80010000"                         // apdu header
                      "44"                               // 0x44 input
                      "00001234"                         // slotId = 0x1234
                      "0102030405060708090A0B0C0D0E0F10" // hash data
                      "00000000000000000000000000000000" //
                      "00000000000000000000000000000000" //
                      "00000000000000000000000000000000" //
                      "00";                              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "11223344556677889900AABBCCDDEEFF" // 31-bit secret
                      "111111111111111111111111111111"   // not enough
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinDataHash hash = {.data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}};
    PinDataSecret secret = {.data = {0}};
    auto ret = ProcPinAuthCmdEnrollLocal(&channel, 0x1234, &hash, &secret);
    EXPECT_EQ(ret, RES_APDU_DATA_ERR);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdEnrollRemoteCaseSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80020000"                         // apdu header
                      "44"                               // 0x44 input
                      "00001234"                         // slotId = 0x1234
                      "0102030405060708090A0B0C0D0E0F10" // hash data
                      "00000000000000000000000000000000" //
                      "00000000000000000000000000000000" //
                      "00000000000000000000000000000000" //
                      "00";                              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinDataRemoteBase base = {.data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}};
    auto ret = ProcPinAuthCmdEnrollRemote(&channel, 0x1234, &base);
    EXPECT_EQ(ret, SUCCESS);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdEnrollRemoteCaseResponseNotSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80020000"                         // apdu header
                      "44"                               // 0x44 input
                      "00001234"                         // slotId = 0x1234
                      "0102030405060708090A0B0C0D0E0F10" // hash data
                      "00000000000000000000000000000000" //
                      "00000000000000000000000000000000" //
                      "00000000000000000000000000000000" //
                      "00";                              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "6985";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinDataRemoteBase base = {.data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}};
    auto ret = ProcPinAuthCmdEnrollRemote(&channel, 0x1234, &base);
    EXPECT_EQ(ret, 0x6985 | (RES_APDU_SW_ERR << 16U));
}

TEST(PinAuthCoreTest, ProcPinAuthCmdAuthLocalTestCaseSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80030000"                         // apdu header
                      "44"                               // 0x44 input
                      "00001234"                         // slotId = 0x1234
                      "0102030405060708090A0B0C0D0E0F10" // hash data
                      "00000000000000000000000000000000" //
                      "00000000000000000000000000000000" //
                      "00000000000000000000000000000000" //
                      "00";                              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "00"                               // status = ok
                      "11223344556677889900AABBCCDDEEFF" // 32-bit secret
                      "11111111111111111111111111111111"
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinDataHash hash = {.data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}};
    PinAuthResult result;
    auto ret = ProcPinAuthCmdAuthLocal(&channel, 0x1234, &hash, &result);
    EXPECT_EQ(ret, SUCCESS);

    std::string expect = "11223344556677889900AABBCCDDEEFF"
                         "11111111111111111111111111111111";
    EXPECT_EQ(result.status, SE_PIN_AUTH_STATUS_OK);
    EXPECT_EQ(TestHelpers::VectorToHexString(result.secret.data, PIN_DATA_SECRET_LEN), expect);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdAuthLocalTestCaseSuccessButSecretSizeIsNotRight)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80030000"                         // apdu header
                      "44"                               // 0x44 input
                      "00001234"                         // slotId = 0x1234
                      "0102030405060708090A0B0C0D0E0F10" // hash data
                      "00000000000000000000000000000000" //
                      "00000000000000000000000000000000" //
                      "00000000000000000000000000000000" //
                      "00";                              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "00"                               // status = ok
                      "11223344556677889900AABBCCDDEEFF" // 31-bit secret
                      "111111111111111111111111111111"
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinDataHash hash = {.data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}};
    PinAuthResult result;
    auto ret = ProcPinAuthCmdAuthLocal(&channel, 0x1234, &hash, &result);
    EXPECT_EQ(ret, RES_APDU_DATA_ERR);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdAuthLocalTestCaseInputPinIsNotCorrect)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80030000"                         // apdu header
                      "44"                               // 0x44 input
                      "00001234"                         // slotId = 0x1234
                      "0102030405060708090A0B0C0D0E0F10" // hash data
                      "00000000000000000000000000000000" //
                      "00000000000000000000000000000000" //
                      "00000000000000000000000000000000" //
                      "00";                              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "01"                               // status = failed
                      "1122"                             // failed cut = 0x1122
                      "AABBCCDD"                         // punish time = 0xaabbccdd
                      "5566"                             // destruct cnt = 0x5566
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinDataHash hash = {.data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}};
    PinAuthResult result;
    auto ret = ProcPinAuthCmdAuthLocal(&channel, 0x1234, &hash, &result);
    EXPECT_EQ(ret, SUCCESS);

    EXPECT_EQ(result.status, SE_PIN_AUTH_STATUS_FAIL);
    EXPECT_EQ(result.freeze.failCnt, 0x1122);
    EXPECT_EQ(result.freeze.punishTime, 0xaabbccdd);
    EXPECT_EQ(result.freeze.destructCnt, 0x5566);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdAuthLocalTestCaseInputPinIsNotCorrectButRspApduSizeIsNotRight)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80030000"                         // apdu header
                      "44"                               // 0x44 input
                      "00001234"                         // slotId = 0x1234
                      "0102030405060708090A0B0C0D0E0F10" // hash data
                      "00000000000000000000000000000000" // pin hash data
                      "00000000000000000000000000000000" // pin hash data
                      "00000000000000000000000000000000" // pin hash data
                      "00";                              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "01"                               // status = failed
                      "1122"                             // failed cut = 0x1122
                      "AABBCCDD"                         // punish time = 0xaabbccdd
                      "5566"                             // destruct cnt = 0x5566
                      "8888"                             // sth not expected
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinDataHash hash = {.data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}};
    PinAuthResult result;
    auto ret = ProcPinAuthCmdAuthLocal(&channel, 0x1234, &hash, &result);
    EXPECT_EQ(ret, RES_APDU_DATA_ERR);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdSetSelfDestructEnableTestCaseSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80070000"                         // apdu header
                      "47"                               // lc = 0x47
                      "00001122"                         // slot id
                      "01"                               // enable = 1
                      "0ABC"                             // max cnt = 0x100
                      "FFFFFFFF05060708090A0B0C0D0E0F10" // pin hash data
                      "00000000000000000000000000000000" // pin hash data
                      "00000000000000000000000000000000" // pin hash data
                      "00000000000000000000000000000000" // pin hash data
                      "00";                              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "00"                               // success
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinDestructConfig config = {.enable = 1, .destructMaxCnt = 0xabc};
    PinDataHash hash = {.data = {0xFF, 0xFF, 0xFF, 0xFF, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}};
    PinConfigResult configResult;
    auto ret = ProcPinAuthCmdSetSelfDestructEnable(&channel, 0x1122, &config, &hash, &configResult);
    EXPECT_EQ(ret, SUCCESS);
    EXPECT_EQ(configResult.status, SE_PIN_CONFIG_STATUS_OK);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdSetSelfDestructEnableTestCaseFailedWithNotSupport)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80070000"                         // apdu header
                      "47"                               // lc = 0x47
                      "00001122"                         // slot id
                      "01"                               // enable = 1
                      "0ABC"                             // max cnt = 0x100
                      "FFFFFFFF05060708090A0B0C0D0E0F10" // pin hash data
                      "00000000000000000000000000000000" // pin hash data
                      "00000000000000000000000000000000" // pin hash data
                      "00000000000000000000000000000000" // pin hash data
                      "00";                              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "07"                               // failed
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinDestructConfig config = {.enable = 1, .destructMaxCnt = 0xabc};
    PinDataHash hash = {.data = {0xFF, 0xFF, 0xFF, 0xFF, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}};
    PinConfigResult configResult;
    auto ret = ProcPinAuthCmdSetSelfDestructEnable(&channel, 0x1122, &config, &hash, &configResult);
    EXPECT_EQ(ret, SUCCESS);
    EXPECT_EQ(configResult.status, SE_PIN_CONFIG_STATUS_FAIL_NO_PERM);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdSetSelfDestructEnableTestCaseFailed)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80070000"                         // apdu header
                      "47"                               // lc = 0x47
                      "00001122"                         // slot id
                      "01"                               // enable = 1
                      "0ABC"                             // max cnt = 0x100
                      "FFFFFFFF05060708090A0B0C0D0E0F10" // pin hash data
                      "00000000000000000000000000000000" // pin hash data
                      "00000000000000000000000000000000" // pin hash data
                      "00000000000000000000000000000000" // pin hash data
                      "00";                              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "08"                               // failed
                      "1234"                             // failed cnt
                      "11223344"                         // punish time
                      "5566"                             // destruct cnt
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinDestructConfig config = {.enable = 1, .destructMaxCnt = 0xabc};
    PinDataHash hash = {.data = {0xFF, 0xFF, 0xFF, 0xFF, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}};
    PinConfigResult configResult;
    auto ret = ProcPinAuthCmdSetSelfDestructEnable(&channel, 0x1122, &config, &hash, &configResult);
    EXPECT_EQ(ret, SUCCESS);
    EXPECT_EQ(configResult.status, SE_PIN_CONFIG_STATUS_FAIL_AUTH_ERR);
    EXPECT_EQ(configResult.freeze.failCnt, 0x1234);
    EXPECT_EQ(configResult.freeze.punishTime, 0x11223344);
    EXPECT_EQ(configResult.freeze.destructCnt, 0x5566);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdSetSelfDestructEnableTestCaseFailedButRspApduSizeIsNotRight)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80070000"                         // apdu header
                      "47"                               // lc = 0x47
                      "00000040"                         // slot id
                      "01"                               // enable = 1
                      "0ABC"                             // max cnt = 0x100
                      "FFFFFFFF05060708090A0B0C0D0E0F10" // pin hash data
                      "00000000000000000000000000000000" // pin hash data
                      "00000000000000000000000000000000" // pin hash data
                      "00000000000000000000000000000000" // pin hash data
                      "00";                              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "08"                               // failed
                      "1234"                             // failed cnt
                      "11223344"                         // punish time
                      "55"                               // destruct cnt size is not right
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinDestructConfig config = {.enable = 1, .destructMaxCnt = 0xabc};
    PinDataHash hash = {.data = {0xFF, 0xFF, 0xFF, 0xFF, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}};
    PinConfigResult configResult;
    auto ret = ProcPinAuthCmdSetSelfDestructEnable(&channel, 64, &config, &hash, &configResult);
    EXPECT_EQ(ret, RES_APDU_DATA_ERR_INDEX_3);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdGetNumSlotsTestCaseSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80080000" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "00003344" // cnt = 0x11223344
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint32_t numSlots = 0;
    auto ret = ProcPinAuthCmdGetNumSlots(&channel, &numSlots);
    EXPECT_EQ(ret, SUCCESS);
    EXPECT_EQ(numSlots, 0x3344);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdGetNumSlotsTestCaseRspApduSizeIsNotRight)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80080000" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "1111"     // cnt size is not right
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint32_t numSlots = 0;
    auto ret = ProcPinAuthCmdGetNumSlots(&channel, &numSlots);
    EXPECT_EQ(ret, RES_APDU_DATA_ERR);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdGetFreezeStatusTestCaseSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80090000" // apdu header
                      "04"       // lc = 4
                      "00000100" // slot id
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "3344"     // failCnt
                      "00005566" // punishTime
                      "7788"     // destructCnt
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinFreezeStatus status;
    auto ret = ProcPinAuthCmdGetFreezeStatus(&channel, 0x100, &status);
    EXPECT_EQ(ret, SUCCESS);
    EXPECT_EQ(status.failCnt, 0x3344);
    EXPECT_EQ(status.punishTime, 0x5566);
    EXPECT_EQ(status.destructCnt, 0x7788);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdSetFreezePolicyTestCaseSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "800A0000" // apdu header
                      "05"       // lc = 5
                      "1122"     // punish start cnt
                      "3344"     // destruct max cnt
                      "01"       // enable
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("009000", response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    auto ret = ProcPinAuthCmdSetFreezePolicy(&channel, 0x1122, 0x3344, 1);
    EXPECT_EQ(ret, SUCCESS);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdSetFreezePolicyTestCaseNotSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "800A0000" // apdu header
                      "05"       // lc = 5
                      "1122"     // punish start cnt
                      "3344"     // destruct max cnt
                      "01"       // enable
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("119000", response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    auto ret = ProcPinAuthCmdSetFreezePolicy(&channel, 0x1122, 0x3344, 1);
    EXPECT_EQ(ret, 0x11);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdSetFreezePolicyTestCaseRspSizeNotRight)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "800A0000" // apdu header
                      "05"       // lc = 5
                      "1122"     // punish start cnt
                      "3344"     // destruct max cnt
                      "01"       // enable
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("9000", response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    auto ret = ProcPinAuthCmdSetFreezePolicy(&channel, 0x1122, 0x3344, 1);
    EXPECT_EQ(ret, RES_APDU_DATA_ERR_INDEX_1);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdGetFreezePolicyTestCaseSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "800B0000" // apdu header
                      "00";      // 00
        EXPECT_EQ(input, expect);

        auto output = "1122" // failCnt
                      "3344" // punishTime
                      "55"   // destructCnt
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint16_t punishStartCnt = 0;
    uint16_t destructMaxCnt = 0;
    uint32_t enableDestructDefault = 0;

    auto ret = ProcPinAuthCmdGetFreezePolicy(&channel, &punishStartCnt, &destructMaxCnt, &enableDestructDefault);
    EXPECT_EQ(ret, SUCCESS);

    EXPECT_EQ(punishStartCnt, 0x1122);
    EXPECT_EQ(destructMaxCnt, 0x3344);
    EXPECT_EQ(enableDestructDefault, 0x55);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdGetFreezePolicyTestCaseRspApduIsNotRightErrIndex3)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "800B0000" // apdu header
                      "00";      // 00
        EXPECT_EQ(input, expect);

        auto output = "1122" // failCnt
                      "3344" // punishTime
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint16_t punishStartCnt = 0;
    uint16_t destructMaxCnt = 0;
    uint32_t enableDestructDefault = 0;

    auto ret = ProcPinAuthCmdGetFreezePolicy(&channel, &punishStartCnt, &destructMaxCnt, &enableDestructDefault);
    EXPECT_EQ(ret, RES_APDU_DATA_ERR_INDEX_3);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdGetFreezePolicyTestCaseRspApduIsNotRightErrIndex2)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "800B0000" // apdu header
                      "00";      // 00
        EXPECT_EQ(input, expect);

        auto output = "1122" // failCnt
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint16_t punishStartCnt = 0;
    uint16_t destructMaxCnt = 0;
    uint32_t enableDestructDefault = 0;

    auto ret = ProcPinAuthCmdGetFreezePolicy(&channel, &punishStartCnt, &destructMaxCnt, &enableDestructDefault);
    EXPECT_EQ(ret, RES_APDU_DATA_ERR_INDEX_2);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdGetFreezePolicyTestCaseRspApduIsNotRightErrIndex1)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "800B0000" // apdu header
                      "00";      // 00
        EXPECT_EQ(input, expect);

        auto output = "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint16_t punishStartCnt = 0;
    uint16_t destructMaxCnt = 0;
    uint32_t enableDestructDefault = 0;

    auto ret = ProcPinAuthCmdGetFreezePolicy(&channel, &punishStartCnt, &destructMaxCnt, &enableDestructDefault);
    EXPECT_EQ(ret, RES_APDU_DATA_ERR_INDEX_1);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdAuthRemotePrepareTestCaseSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80040000"                                                         // apdu header
                      "0C"                                                               // lc = 0xc
                      "0000AABB"                                                         // slot id = 0xaabb
                      "000000000000CCDD"                                                 // session = 0xccdd
                      "00";                                                              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "010102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F" // service pk 64-bit
                      "020102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F" // service pk 64-bit
                      "03112233445566778899AABBCCDDEEFF"                                 // service challenge 16-bit
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinDataRemoteServiceChallenge challenge;
    (void)memset_s(&challenge, sizeof(challenge), 0, sizeof(challenge));
    auto ret = ProcPinAuthCmdAuthRemotePrepare(&channel, 0xaabb, 0xccdd, &challenge);
    EXPECT_EQ(ret, SUCCESS);

    auto pk = TestHelpers::VectorToHexString(challenge.pk.data, sizeof(challenge.pk.data));
    EXPECT_EQ(pk, "010102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
                  "020102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F");

    auto nonce = TestHelpers::VectorToHexString(challenge.nonce.data, sizeof(challenge.nonce.data));
    EXPECT_EQ(nonce, "03112233445566778899AABBCCDDEEFF");
}

TEST(PinAuthCoreTest, ProcPinAuthCmdAuthRemotePrepareTestCaseRspAuduSizeIsNotEnough)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80040000"                                                         // apdu header
                      "0C"                                                               // lc = 0xc
                      "0000AABB"                                                         // slot id = 0xaabb
                      "000000000000CCDD"                                                 // session = 0xccdd
                      "00";                                                              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "010102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F" // service pk 64-bit
                      "020102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F" // service pk 64-bit
                      "0311223344556677"                                                 // service challenge not right
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinDataRemoteServiceChallenge challenge;
    (void)memset_s(&challenge, sizeof(challenge), 0, sizeof(challenge));
    auto ret = ProcPinAuthCmdAuthRemotePrepare(&channel, 0xaabb, 0xccdd, &challenge);
    EXPECT_EQ(ret, RES_APDU_DATA_ERR_INDEX_2);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdAuthRemoteProcessTestCaseSuccessAndAuthSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80050000"                                                         // apdu header
                      "7C"                                                               // lc = 0x7c
                      "0000AABB"                                                         // slot id = 0xaabb
                      "000000000000CCDD"                                                 // session = 0xccdd
                      "010102030405060708090A0B0C0D0E0F00000000000000000000000000000000" // service pk 64-bit
                      "0000000000000000000000000000000000000000000000000000000000000000" // service pk 64-bit
                      "03112233445566778899AABBCCDDEEFF"                                 // service challenge 16-bit
                      "04112233445566778899AABBCCDDEEFF00000000000000000000000000000000" // client hmac 32-bit
                      "00";                                                              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "00"                                                               //  auth success
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinDataRemoteClientProof proof = {
        .pk = {0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
        .nonce = {0x03, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF},
        .hmac = {0x04, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF},
    };

    PinAuthResult result;
    (void)memset_s(&result, sizeof(result), 0, sizeof(result));

    auto ret = ProcPinAuthCmdAuthRemote(&channel, 0xaabb, 0xccdd, &proof, &result);
    EXPECT_EQ(ret, SUCCESS);
    EXPECT_EQ(result.status, SE_PIN_AUTH_STATUS_OK);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdAuthRemoteProcessTestCaseSuccessAndAuthNotSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80050000"                                                         // apdu header
                      "7C"                                                               // lc = 0x7c
                      "0000AABB"                                                         // slot id = 0xaabb
                      "000000000000CCDD"                                                 // session = 0xccdd
                      "010102030405060708090A0B0C0D0E0F00000000000000000000000000000000" // service pk 64-bit
                      "0000000000000000000000000000000000000000000000000000000000000000" // service pk 64-bit
                      "03112233445566778899AABBCCDDEEFF"                                 // service challenge 16-bit
                      "04112233445566778899AABBCCDDEEFF00000000000000000000000000000000" // client hmac 32-bit
                      "00";                                                              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "03"                                                               //  auth not success
                      "1122"                                                             // fail cnt = 0x1122
                      "AABBCCDD"                                                         // punish time = 0xaabbccdd
                      "EEFF"                                                             // destruct cnt = 0xeeff
                      "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    PinDataRemoteClientProof proof = {
        .pk = {0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
        .nonce = {0x03, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF},
        .hmac = {0x04, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF},
    };

    PinAuthResult result;
    (void)memset_s(&result, sizeof(result), 0, sizeof(result));

    auto ret = ProcPinAuthCmdAuthRemote(&channel, 0xaabb, 0xccdd, &proof, &result);
    EXPECT_EQ(ret, SUCCESS);
    EXPECT_EQ(result.status, SE_PIN_AUTH_STATUS_DESTRUCT);
    EXPECT_EQ(result.freeze.failCnt, 0x1122);
    EXPECT_EQ(result.freeze.punishTime, 0xaabbccdd);
    EXPECT_EQ(result.freeze.destructCnt, 0xeeff);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdAuthRemoteAbortTestCaseSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80060000"         // apdu header
                      "0C"               // lc = 0x0c
                      "0000AABB"         // slot id = 0xaabb
                      "000000000000CCDD" // session = 0xccdd
                      "00";              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    auto ret = ProcPinAuthCmdAuthRemoteAbort(&channel, 0xaabb, 0xccdd);
    EXPECT_EQ(ret, SUCCESS);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdAuthRemoteAbortTestCaseNotSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80060000"         // apdu header
                      "0C"               // lc = 0x0c
                      "0000AABB"         // slot id = 0xaabb
                      "000000000000CCDD" // session = 0xccdd
                      "00";              // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "9043";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    auto ret = ProcPinAuthCmdAuthRemoteAbort(&channel, 0xaabb, 0xccdd);
    EXPECT_NE(ret, SUCCESS);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdEraseSingleSlotTestCaseSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "800C0000" // apdu header
                      "04"       // lc = 0x0c
                      "0000AABB" // slot id = 0xaabb
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    auto ret = ProcPinAuthCmdEraseSingleSlot(&channel, 0xaabb);
    EXPECT_EQ(ret, SUCCESS);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdEraseSingleSlotTestCaseNotSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "800C0000" // apdu header
                      "04"       // lc = 0x0c
                      "0000AABB" // slot id = 0xaabb
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "1234";    // not success
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    auto ret = ProcPinAuthCmdEraseSingleSlot(&channel, 0xaabb);
    EXPECT_NE(ret, SUCCESS);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdEraseAllSlotTestCaseSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "800D0000" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "9000";
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    auto ret = ProcPinAuthCmdEraseAllSlot(&channel);
    EXPECT_EQ(ret, SUCCESS);
}

TEST(PinAuthCoreTest, ProcPinAuthCmdEraseAllSlotTestCaseNotSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "800D0000" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);
        auto output = "6985";    // not success
        TestHelpers::StringFillUp(output, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    auto ret = ProcPinAuthCmdEraseAllSlot(&channel);
    EXPECT_NE(ret, SUCCESS);
}
} // namespace UnitTest
} // namespace SeBaseServices
} // namespace OHOS